home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Macintosh Demo Applications CD
/
Apple-MacintoshDemoApplicationsCD-1.0-1992.iso
/
More Information
/
QuicKeys
/
For Programmers Only.sea
/
Inside QuicKeys 2™ (v2.1)
< prev
next >
Wrap
Text File
|
1991-06-22
|
24KB
|
564 lines
Inside QuicKeys 2™ Extensions
June 1991 Revision
Copyright © 1990-91 CE Software, Inc.
What are Extensions
Even though it wasn't designed to do so, the original QuicKeys was extended
by several people to call QuicKeys functions from within their program.
In QuicKeys 2™, not only can an application have QuicKeys 2 perform functions
for it, but we have taken the idea of extensibility a leap forward and added
what we call extensions.
Extensions let you add almost any functionality directly to QuicKeys 2 that will
be available to users in ANY application. To the user, an extension looks and
works just like any other action that QuicKeys 2 can perform, such as a menu
selection or click. Extensions can be defined individually or be part of a
sequence of QuicKeys 2 actions. And since an extension is in its own file
independent of QuicKeys 2, they can be added or removed without changing
QuicKeys 2.
This document provides you with the information you will need to design and
build your own extensions. On the disk with this document is source for
a sample extension written in C and Pascal. The function prototypes and
structures discussed in the document are presented in C. The structures
defined here can be found in extensions.h in the C Examples folder or in
extensions.p in the Pascal Examples folder. You can also refer to
the source in the Pascal Examples folder for the Pascal declarations of the
functions described here.
Extension QuicKey Format
Each type of action that QuicKeys 2 performs is called a QuicKey. A QuicKey is
a sequence of bytes that contain the information necessary to perform the action
that is described. For example, a menu selection QuicKey contains the
information necessary to perform the requested menu selection such as the
menu and item name. The QuicKey format for an extension is largely up to the
extension developer. There are only two rules that QuicKeys 2 enforces on an
extension's QuicKey. The QuicKey must always start with the common data header
called the ExtensionDataHeader and the total length including this header must
not be greater than 2048 bytes.
The format of the ExtensionDataHeader is:
struct ExtensionDataHeader {
unsigned char strTitle[16];
OSType ostCreator;
short wLength;
};
strTitle is the name of the QuicKey. It's initial value is the name of your
extension truncated to 15 characters. Your user interface routine may
change it.
ostCreator is the extension's creator obtained from it's Finder info by
QuicKeys 2. You should not change this field.
wLength is total length of the QuicKey including this header. The maximum
length is 2048 bytes.
Extension Structure
Each extension is a separate file in the QuicKeys 2 Extensions folder. The file
type of each extension must be 'QKex' and the creator must be unique. QuicKeys 2
uses the creator to find the extension when an extension's QuicKey is being
played. If two extensions with the same creator are present in the Extensions
folder, it's quite likely that a QuicKey for one extension will be executed by
the other extension with "interesting" and possibly spectacular results.
CE Software, Inc. will provide a creator registry to ensure that each extension
will have a unique creator. Once you finish writing your extension you will need
to register your Creator with us. You can do this by sending a letter, fax,
or electronic message to us at one of the addresses found at the end of this
document.
Each extension is divided into two parts. A user interface routine and an
execution routine. The user interface routine is used when the user is
defining or editing a QuicKey for your extension in QuicKeys 2. The
execution routine is generally called when a QuicKey for your extension is
being played by QuicKeys 2. Your execution routine is also called at certain
other well-defined times and is described in detail below.
User Interface Routine
The user interface part of the extension is stored in a code resource with the
type 'QkyC' and id -14348. This code resource is loaded when the user is
defining or editing a QuicKey for your extension in QuicKeys 2. QuicKeys 2
will append your dialog item list (type 'DITL' with id -14348) to the standard
extension edit dialog so you can provide almost any interface you wish. As
you will see from the description below and in the sample extension on this
disk, writing the user interface part is a lot like writing a control panel.
The entry point to the extension is at the beginning of the resource and is:
pascal long ExtensionUI(short wSelector, DialogPtr pDialog,
short wHitItem, short wNumItems, ExtensionData* pKeyData,
long lRefCon);
wSelector identifies what QuicKeys 2 wants the user interface routine to do.
Possible values are
newUI: You're being called to make a new QuicKey.
Initialize your private data accordingly. Called after your
dialog items have been added to QuicKeys 2 dialog but before
your initialize call.
initUI: Called after your dialog items have been added to QuicKeys 2
dialog. Your dialog is still invisible. You should initialize
your dialog items during this call.
hitUI: The user clicked or typed in one of your items. The item
number is in wHitItem. Since your dialog items are appended
to QuicKeys 2 dialog, you must subtract wNumItems from wHitItem
to figure out which of your dialog items were hit.
doneUI: Called after user selected OK or Cancel. Do any cleanup here.
You should always treat your data as if OK was selected. You
are actually working on a copy of your data which will be
discarded if cancel is hit. See pKeyData for more information.
pDialog is the Dialog that QuicKeys 2 will display.
wHitItem is only valid when wSelector is "hit". It contains the dialog item
number that the user selected. You need to subtract wNumItems from this
value to find out which of your dialog items was hit.
wNumItems contains the number of dialog items in pDialog that belong
to QuicKeys 2.
pKeyData is the address of a copy of your QuicKey. It begins with an
ExtensionDataHeader and is followed by the data for this QuicKey. Any
changes made to this copy of your QuicKey are only saved if the user
selects OK. If the user selects Cancel, this copy is discarded and
your QuicKey is not changed.
lRefCon serves as both return value and storage for your user interface
routine. If you return -1, QuicKeys 2 will display an generic edit dialog.
The value returned by one call to your user interface routine will be passed
in lRefCon when you are called again. This field works just like cdevValue
in the control panel programming interface.
QuicKeys 2 will display a small icon and extension version information if found
in your file. The small icon is resource type 'SICN' with id -14348 and version
information is obtained from the resource 'vers' with id 1.
Your user interface routine may use any other resources as necessary but to
avoid potential conflicts, their ids should be restricted to -14348 to -14343.
Hierarchical Menus
If you intend to use hierarchical menus in your extension, you must be careful to
avoid conflicts with any existing menus. The only way to do this is to find an
unused menu id when creating your hierarchical menu. If you fail to do this, your
extension will fail to work or, even worse, will adversely affect the application
that the extension was used over.
A simple routine to find an available menu id is:
short
GetMenuID() {
short wMenuID = 255; /* start at biggest valid hierarchical menu id */
while (wMenuID > 1) { /* keep trying until we run out of menu ids */
if (GetMHandle(wMenuID) == nil) /* if not in use, we're finished */
break;
wMenuID--; /* try the next id */
}
return wMenuID; /* done. return the id to the caller */
}
You'd use this routine as follows:
MenuHandle hPopup = NewMenu(GetMenuID(), "\pmenu");
Execution Routine
The extension's execution routine is loaded by QuicKeys 2 at boot time and
remains resident in memory. It is also a code resource in your extension file
of type 'QkyC' with id -14347. You must remember to set the system heap bit for
this resource so it will be loaded into the system heap (if you don't, you'll
almost certainly cause crashes).
Unlike the user interface routine, the execution routine begins with a structure
that QuicKeys 2 uses to communicate with the extension and the extension can use
to control how QuicKeys 2 calls it. This structure is part of a linked list of
all extensions currently installed. The entry point to the extension is
immediately following this structure.
The format of this structure is:
struct ExecuteQueue {
ExecuteQueue* pNext;
OSType ostCreator;
unsigned short flags;
unsigned char strFName[32];
char sicn[32];
long lRefCon;
};
pNext points to the next extension in the linked list. It is populated
by QuicKeys 2. You should not change this field.
ostCreator is your extension's creator from your Finder info. It is populated
by QuicKeys 2. You should not change this field. When QuicKeys 2 plays an
extension's QuicKey, it uses ostCreator to find the execution routine that
the QuicKey belongs to.
flags are used to ask QuicKeys 2 for special processing. See the QuicKeys 2
header files for the definitions of these flags. All undefined bits in
flags are reserved for future use and must be zero. The following bits are
defined:
PeriodicFlag
The PeriodicFlag bit asks QuicKeys 2 to call you every time
GetNextEvent or EventAvail are called or when QuicKeys 2 gets time
during SystemTask. PeriodicFlag is defined as 0x0001.
AbortFlag
The AbortFlag asks QuicKeys 2 to call you when the user aborts playback
by clicking the mouse or if QuicKeys 2 aborts playback because of an
error. AbortFlag is defined as 0x0002;
If you are doing something in your extension that expects mouse down
events (such as displaying a dialog), make sure that AbortFlag is
off before doing so. Conversely, AbortFlag should only be on when it
makes sense to do so. If you leave AbortFlag on in your extension
and another extension comes along and expects to see mousedowns, the
other extension will NOT see mouse down events - even if the other
extension sets its own AbortFlag to off. In other words, QuicKeys 2
will treat mouse down events as aborts if ANY extension has it's
AbortFlag set.
DontLoadFlag
The DontLoadFlag informs QuicKeys 2 that this extension is not to be
loaded. It is useful when you are writing an extension that depends on
a specific software and/or hardware configuration to be present. It may
only be set by your execute routine's InitX call. If the bit is set, the
extension will not be displayed in the Define menu nor will users be able
to edit keys for that extension. DontLoadFlag is defined as 0x8000. This
flag is ignored by versions of QuicKeys 2 prior to 2.1. See the section
on "Installation and Availability Control" below for more information.
strFName is your extension's file name. It is populated by QuicKeys 2.
You should not change this field.
sicn contains the small icon that QuicKeys 2 displays. Your executable is
responsible for populating this field.
lRefCon is available for your extension's use.
As mentioned earlier, the entry point to your extension is immediately after
the ExecuteQueue structure. QuicKeys 2 calls your execution routine as:
pascal void Execute(short wSelector, PublicQK2Globals* pQK2Globals);
wSelector identifies the type of call. Possible values are:
initX Your execution routine was just loaded into the system
heap (remember it's during boot time). Initialize private
data and the sicn field in your ExecuteQueue header now.
This is the only time you're called where your file is open.
regularX QuicKeys 2 is playing a QuicKey for your extension. A copy
of the QuicKey is in pQK2Globals->ucaCurKey.
periodicX You have set the PeriodicFlag bit in your ExecuteQueue flags.
Register D3 contains the type of periodic call. Values are:
periodicDoRun = SystemTask driver run
periodicGNE = GetNextEvent
periodicEAvail = EventAvail
If you need the periodic type and do not wish to write any
assembler code, see the section on commonExecute.a below.
abortX You have set the AbortFlag bit in your ExecuteQueue flags.
You may not move memory during this call. You should set
a flag in your extension to indicate that an abort was
caught and turn off AbortFlag.
pQK2Globals points to QuicKeys 2 globals area. There are a few fields
there that may be of interest. The entire globals area must be
treated as read only and all undefined areas in it are considered private
and should not be used.
struct PublicQK2Globals {
char private1[524];
short wDestVol;
long lDestDirID;
long lPrefsDir;
long lQKDir;
long lKeySetDir;
long lMacroDir;
long lSeqDir;
long lExtDir;
long lClipDir;
char private3[70];
ExecuteQueue* pExtensions;
char private4[1338];
short wCurKeyType;
char ucaCurKey[2048];
Str255 strTypeString;
};
wDestVol contains the refnum of the volume containing QuicKeys 2 (and
your extension).
lDestDirID is the DirID of the system folder.
lPrefsDir is the DirID of the folder "Preferences" (in the System folder).
lQKDir is the DirID of the folder "QuicKeys Folder" (in the Preferences folder)
lKeySetDir, lMacroDir, lSeqDir, and lClipDir are DirIDs of folders in
the QuicKeys Folder. lClipDir contains files used by the Grab Ease™,
Paste Ease™, and Type Ease™ extensions.
lExtDir contains the DirID of the Extensions directory. You can use
wDestVol, lExtDir and fName from the ExecuteQueue to open your
extension to fetch resources, etc. The fields here contain DirIDs of
other folders used by QuicKeys 2.
pExtensions points to the first extension in QuicKeys 2 linked list
of extensions.
wCurKeyType is the type of QuicKey contained in ucaCurKey.
ucaCurKey contains a copy of the QuicKey currently being played.
strTypeString is the only read/write area available for your use. If
you want QuicKeys 2 to type a string for you (as if the user typed it on
the keyboard), place that string in this field. Before you copy the string
into this field, make sure that QuicKeys is not currently typing something
by looking at strTypeString[0]. Only if that byte is zero, is it safe to
load this field with the string to type.
commonExecute.a
commonExecute.a is a shortcut provided for creating execution routines in C++,
C, or Pascal. It avoids the need for you to write assembler code to construct
execution routines. commonExecute provides space for your ExecuteQueue and
calls your execution routine with the information it is most likely to need.
Think C users can refer to SampleXHdr.c, which provides the same functionality.
commonExecute.a must be linked first so the ExecuteQueue is at the beginning of
the code resource.
commonExecute.a expects your routine to be defined as:
pascal void doExecute(short wSelector, ExtensionData* pMyData,
ExecuteQueue* pQueue, short wPeriodicType);
wSelector is passed by QuicKeys 2.
pMyData is a pointer to your QuicKey (pQK2Globals->ucaCurKey).
Remember that it is only valid when wSelector is regularX.
pQueue points to your ExecuteQueue record.
wPeriodicType is only valid when wSelector is periodicX. It contains
the type of periodic call. Possible values are:
periodicDoRun = SystemTask driver run
periodicGNE = GetNextEvent
periodicEAvail = EventAvail
QuicKeys 2 Driver
As you might have guessed, QuicKeys 2 installs a driver named ".QuicKeys".
Although you might not need the functionality provided by these documented
calls, they are available for your use. The calls described here are not only
available to extensions but to any application as well.
Use OpenDriver to open the QuicKeys 2 driver. You should never close the
driver.
Below is a list of available control calls and their csCode value within parenthesis.
QK2GetGlobals(8) Returns a pointer to QuicKeys 2 globals area
in csParam. This area is read-only.
QK2PlayByName(17) Plays a QuicKey with the given name. Pass a pointer to
the address of the name in csParam. QuicKeys 2 will first
look through the current application's set for the QuicKey.
If not found there, the universal set is examined. If more
than one QuicKey with the same name is defined in the same
set, you have no guarantee about which one will be played.
Here's how you would use the high level Control call to play
by name is:
StringPtr pName = (StringPtr)"\pQuickPanel";
wErr = OpenDriver(QuicKeysDriverName, &wRefNum);
wErr = Control(wRefNum, QK2PlayByName, &pName);
The corresponding calls using PBControl are:
CntrlParam pb;
pb.ioCRefNum = wRefNum;
pb.csCode = QK2PlayByName;
*(char**)&pb.csParam[0] = "\pQuickPanel";
wErr = PBControl(&pb, false);
The corresponding PBControl example in Pascal is:
macro: str255;
pb: ParamBlockRec;
pb.ioCRefNum := wRefNum;
pb.csCode := QK2PlayByName;
macro := 'QuickPanel';
pb.csParam[0] := hiword(longint(@macro));
pb.csParam[1] := loword(longint(@macro));
wErr := PBControl(@pb, false);
If no QuicKey with the given name is found, an error is
returned.
QK2PlayByPtr(18) Plays a QuicKey with the given name. Pass the key type in
the word at csParam. Pass the address of the QuicKey to
play in csParam+2
QK2GetStatus(19) Returns the current QuicKeys 2 status.
The word at csParam is:
0 = idle
not 0 = busy
The word at csParam + 2 is:
QK2IsDisabled = QuicKeys 2 is turned off (see QK2OnOff)
QK2InUserInterface = in user interface
QK2BusyNotPlaying = busy but not currently playing back
QK2IsIdle = idle
QK2InPlayFast = in Sequence Playback
QK2InPlayFastPaused = paused in Sequence Playback
QK2InRecordFast = in Sequence Record
QK2InRecordFastPaused = paused in Sequence Record
QK2InPlayRT = in Realtime Playback
QK2InPlayRTPaused = paused in Realtime Playback
QK2InRecordRT = in Realtime Record
QK2InRecordRTPaused = paused in Realtime Record
QK2IsIdle will be returned if QuicKeys is busy (csParam
not 0) but the reason for being busy is not any of the
other status codes described above.
QK2Kill(20) Stops any executing QuicKey or sequence. If you have
paused QuicKeys 2 with a QK2Pause command, you must
resume QuicKeys 2 before issuing this command.
QK2OnOff(21) Pass 0 in the word at csParam to turn QuicKeys 2 on.
Pass -1 in the word at csParam to turn QuicKeys 2 off.
QK2Pause(23) Pass 0 in the word at csParam to pause QuicKeys 2.
Pass -1 in the word at csParam to resume QuicKeys 2.
You could use this so you can do something that
QuicKeys 2 might accidentally interpret as something
for it to do.
QK2GetPosition(24) Get the current position in the sequence being played.
The longword at csParam contains the position. An error
is returned if QuicKeys 2 is not playing back.
QK2SetPosition(25) Set the current position in the sequence being played.
The longword at csParam contains the new position. An error
is returned if QuicKeys 2 is not playing back.
QK2GetVersion(26) Returns a long word at csParam that contains the current
QuicKeys 2 version. The format is the same as is stored in
the 'vers' id 1 resource.
Installation and Availability Control
QuicKeys 2 was enhanced in release 2.1 to provide extensions with the ability to
control their installation and whether or not they are available for use. This
new feature is extremely important when you have an extension that should not be
available to users under certain circumstances (like a System 7 savy extension when
the user is running System 6).
A new resource may be added to extensions that will mark them as requiring System 7.
The rez statement for this resource is:
data 'FLAG' (-14348) {$"8000"}; /* mark extension as requiring System 7 */
Other bits in this resource are reserved for future use and should be zero.
If this resource is present and the high order bit is set:
1) QuicKeys will not load the extension when running under System 6. Users will
not be able to define or edit keys for the extension.
2) QKInstall will not install the extension when running under System 6.
3) Extension Manager will warn users before installing the extension when running
under System 6.
If the level of control is more sophisticated than just System 6 vs. System 7,
you can perform the necessary tests during the extension's initX routine. If
the extension is NOT to be loaded, set the DontLoadFlag in the extension's flags
word before returning from your initX routine. Setting the flag will prevent
users from defining or editing keys for your extension.
Both of these schemes are not provided in versions of QuicKeys 2 prior to 2.1.
Versions of QuicKeys 2 prior to 2.1 will always load and display all extensions
present in the extensions folder.
Balloon Help
Balloon help can be easily added to your extension by following these steps:
1) include BalloonTypes.r in your rez file.
2) append the following item at the end of your dialog item list:
{ 0, 0, 0, 0}, HelpItem { disabled, HMScanhdlg {-14348} },
3) add a dialog help resource. The item in this resource correspond to the
items in your DITL resource. See the file Sample.r for a detailed example.
4) add this snippet of code to your user interface routine's to set the number of
dialog items to skip field in the dialog help resource:
Handle hHelp;
hHelp = GetResource('hdlg', -14348);
if (hHelp != nil)
BlockMove((Ptr)&wFirstItem, *hHelp + 2, sizeof(short));
Extension Resource Summary
The resources listed below are the minimal set needed for an extension.
Your extension may use any other resources as necessary but to
avoid potential conflicts, their ids should be restricted to -14348 to -14343.
'vers' (1) Version number displayed in user interface dialog
'DITL' (-14348, Purgeable) Your dialog items for define/edit dialog
'hdlg' (-14348) Balloon help items (optional)
'SICN' (-14348) Small icon for your extension
'QkyC' (-14348, Purgeable) User interface routine code
'QkyC' (-14347, SysHeap) Execution routine code
'FLAG' (-14348) Optional. If present and contains 0x8000, extension only
loaded when running System 7.
How to reach CE Software, Inc.
If you would like to be included in any updates to this document, or need to
ask a question regarding development of extensions, send a message containing
your name, company, title, mailing address, daytime phone number, and electronic
address to us at one of these electronic addresses.
America Online: CESOFTWARE
AppleLink: CESOFTWARE
CompuServe: 76136,2137
CONNECT: CESOFTWARE
FAX: 515-224-4534
GEnie: CESOFTWARE
MCI Mail: CESOFTWARE
QuickMail: 515-224-1721
The first line of the body of your message should read:
ATTN: QuicKeys DS
Your message will be forwarded to the correct person and you will receive the
information that you need.
If you do not have access to an electronic service, write to:
CE Software, Inc.
P.O. Box 65580
West Des Moines, IA 50265
Attn: QuicKeys Developer Services
Free Listing
After writing your extension, send us a copy. We’ll add your extension to a
list of extensions and their authors. This list will be published electronically
over several well-used services.